package com.heima.article.service.impl;

import com.heima.article.entity.ApArticle;
import com.heima.article.entity.ApHotArticles;
import com.heima.article.mapper.ApHotArticlesMapper;
import com.heima.article.service.ApArticleService;
import com.heima.article.service.ApHotArticlesService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.exception.LeadException;
import com.heima.common.util.JsonUtils;
import com.heima.model.article.dtos.ArticleBehaviorStreamMsg;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Set;

/**
 * <p>
 * 热文章表 服务实现类
 * </p>
 *
 * @author HM
 * @since 2023-03-22
 */
@Service
public class ApHotArticlesServiceImpl extends ServiceImpl<ApHotArticlesMapper, ApHotArticles> implements ApHotArticlesService {
    private static final String KEY = "leadnew:article:";
    private static final String KEY_HOT = "leadnew:article:hotlist";
    @Autowired
    private ApArticleService apArticleService;
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public void updateBehavior() {
        Set<String> articleIds = redisTemplate.boundSetOps("article_score_set").members();
        for (String articleId : articleIds) {
            String behaviorStr = redisTemplate.boundValueOps(articleId + "").get();

            ArticleBehaviorStreamMsg articleBehaviorStreamMsg = JsonUtils.toBean(behaviorStr, ArticleBehaviorStreamMsg.class);
            ApArticle apArticle = apArticleService.getById(articleBehaviorStreamMsg.getArticleId());
            Long views = apArticle.getViews() + articleBehaviorStreamMsg.getViews();
            Long likes = apArticle.getLikes() + articleBehaviorStreamMsg.getLikes();
            Long comments = apArticle.getComments() + articleBehaviorStreamMsg.getComment();
            Long collections = apArticle.getCollection() + articleBehaviorStreamMsg.getCollection();
            apArticle.setViews(views);
            apArticle.setLikes(likes);
            apArticle.setComments(comments);
            apArticle.setCollection(collections);
            apArticleService.updateById(apArticle);
            redisTemplate.delete(articleId + "");

        }
        redisTemplate.delete("article_score_set");
    }

    @Override
    public void calcArticlrscore(String param) {
//Set<String, String> articleIdSet = redisTemplate.boundSetOps("article_score_set").getOperations();
        //查询最近五天数据
        Integer days = Integer.parseInt(param);
        LocalDateTime localDateTime = LocalDate.now().minusDays(days).atStartOfDay();
        List<ApArticle> list = apArticleService.getLastestArticle(localDateTime);

        if (list == null) {
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //计算分值
        for (ApArticle apArticle : list) {
            double articlrscore = calcArticlrscore(apArticle);
            redisTemplate.boundZSetOps(KEY_HOT).add("" + apArticle.getId(), articlrscore);

            redisTemplate.boundValueOps(KEY + apArticle.getId()).set(JsonUtils.toString(apArticle));
        }

    }

    @Override
    public void updateHotArticle(ArticleBehaviorStreamMsg msg) {
        ApArticle apArticle = new ApArticle();
        apArticle.setViews(Long.valueOf(msg.getViews()));
        apArticle.setLikes(Long.valueOf(msg.getLikes()));
        apArticle.setComments(Long.valueOf(msg.getComment()));
        apArticle.setCollection(Long.valueOf(msg.getCollection()));

        double articlrscore = calcArticlrscore(apArticle);

        redisTemplate.boundZSetOps(KEY_HOT).incrementScore("" + msg.getArticleId(), articlrscore);
        // 记录行为详细数据
        // 存两个结构：第1个的key是2023-04-02:articleId, value是行为数据的json
        //           第2个的key是固定值，比如：2023-04-02:article_score_set   value是set结构，内容是需要同步的articleId的列表
        // 将来定时任务同步redis数据到mysql的时候，先根据第2个key找到所有需要同步到articleId
        // 根据第一个key，找到是需要同步的行为数据
        // xxljob起一个定时任务，把redis中的行为数据，写入到数据库
        redisTemplate.boundSetOps("article_score_set").add(msg.getArticleId() + "");

        String behaviorRedis = redisTemplate.boundValueOps(msg.getArticleId() + "").get();
        if (behaviorRedis == null) {
            redisTemplate.boundValueOps(msg.getArticleId() + "").set(JsonUtils.toString(msg));
        } else {
            ArticleBehaviorStreamMsg behaviorStreamMsg = JsonUtils.toBean(behaviorRedis, ArticleBehaviorStreamMsg.class);
            behaviorStreamMsg.setViews(behaviorStreamMsg.getViews() + msg.getViews());
            behaviorStreamMsg.setLikes(behaviorStreamMsg.getLikes() + msg.getLikes());
            behaviorStreamMsg.setComment(behaviorStreamMsg.getComment() + msg.getComment());
            behaviorStreamMsg.setCollection(behaviorStreamMsg.getCollection() + msg.getCollection());
            redisTemplate.boundValueOps(msg.getArticleId() + "").set(JsonUtils.toString(behaviorStreamMsg));
        }


    }

    public double calcArticlrscore(ApArticle apArticle) {
        double score = 0;
        score += apArticle.getViews() == null ? 0 : apArticle.getViews();
        score += apArticle.getLikes() == null ? 0 : apArticle.getLikes() * 3;
        score += apArticle.getComments() == null ? 0 : apArticle.getComments() * 5;
        score += apArticle.getCollection() == null ? 0 : apArticle.getCollection() * 8;
        return score;

    }
}
